﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GalaSoft.MvvmLight.Command;
using Bymed.SpineScan.WPF.Model;
using Bymed.SpineScan.WPF.Shared;
using GalaSoft.MvvmLight.Messaging;
using Bymed.SpineScan.DataModel;
using System.Collections.ObjectModel;

namespace Bymed.SpineScan.WPF.ViewModel.TestItemViewModel
{
    public class SingleTestItemViewModel : MyViewModelBase
    {
        public bool IsCustomizedTestItem { get; set; }
        public string TestItemType { get; set; }

        /// <summary>
        /// Initializes a new instance of the SingleTestItemViewModel class.
        /// </summary>
        public SingleTestItemViewModel(IDataService dataService)
            : base(dataService)
        {
            InitializeParameters();
        }

        /// <summary>
        /// Generate the graph data. For ScoliosisATI ONLY.
        /// </summary>
        /// <param name="graphRawData">The graph raw data comes from hardware.</param>
        public void GerenateGraphData(IList<double> graphRawData)
        {
            // Clear history data
            GraphData.Clear();

            // Add the new data
            for (int i = 0; i < graphRawData.Count; i++)
            {
                // Test result
                GraphData.Add(new KeyValuePair<int, double>(i, graphRawData[i]));
            }
        }

        /// <summary>
        /// Setup the test position name based on TestItemBase.Position.
        /// </summary>
        /// <param name="testPosition">The value of TestItemBase.Position</param>
        public void SetupTestPositionName(TestItemBase.Position testPosition)
        {
            if (testPosition == TestItemBase.Position.Thoracic)
            {
                TestPositionName = "胸椎";
            }
            else if (testPosition == TestItemBase.Position.Lumbar)
            {
                TestPositionName = "腰椎";
            }
        }

        /// <summary>
        /// Set the value for FormattedTestResult property.
        /// </summary>
        public virtual void SetFormattedTestResult()
        {
            if (FirstTestResult.HasValue || SecondTestResult.HasValue)
            {
                if (FirstTestResult != -1 && SecondTestResult != -1)
                {
                    FormattedTestResult = string.Format("{0}{1}° {2}{3}°",
                        FirstTestResultLabel, FirstTestResult,
                        SecondTestResultLabel, SecondTestResult);
                }
                else if (FirstTestResult == -1)
                {
                    FormattedTestResult = string.Format("{0}NA {1}{2}°",
                        FirstTestResultLabel,
                        SecondTestResultLabel, SecondTestResult);
                }
                else if (SecondTestResult == -1)
                {
                    FormattedTestResult = string.Format("{0}{1}° {2}NA",
                        FirstTestResultLabel, FirstTestResult,
                        SecondTestResultLabel);
                }
            }
        }

        /// <summary>
        /// Check if current test is finished.
        /// </summary>
        /// <returns>True means finished. False means not.</returns>
        public virtual bool CheckIfTestFinished()
        {
            if (!FirstTestResult.HasValue || !SecondTestResult.HasValue || 
                FirstTestResult == 0 || SecondTestResult == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// Initialize all necessary parameters.
        /// </summary>
        protected virtual void InitializeParameters() { }

        /// <summary>
        /// The <see cref="SequenceNumber" /> property's name.
        /// </summary>
        public const string SequenceNumberPropertyName = "SequenceNumber";

        private int _sequenceNumber = 0;

        /// <summary>
        /// Sets and gets the SequenceNumber property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public int SequenceNumber
        {
            get
            {
                return _sequenceNumber;
            }

            set
            {
                if (_sequenceNumber == value)
                {
                    return;
                }

                RaisePropertyChanging(SequenceNumberPropertyName);
                _sequenceNumber = value;
                RaisePropertyChanged(SequenceNumberPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="TestItemTitle" /> property's name.
        /// </summary>
        public const string TestItemTitlePropertyName = "TestItemTitle";

        private string _testItemTitle = string.Empty;

        /// <summary>
        /// Sets and gets the TestItemTitle property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string TestItemTitle
        {
            get
            {
                return _testItemTitle;
            }

            set
            {
                if (_testItemTitle == value)
                {
                    return;
                }

                RaisePropertyChanging(TestItemTitlePropertyName);
                _testItemTitle = value;
                RaisePropertyChanged(TestItemTitlePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="TestItemName" /> property's name.
        /// </summary>
        public const string TestItemNamePropertyName = "TestItemName";

        private string _testItemName = string.Empty;

        /// <summary>
        /// Sets and gets the TestItemName property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string TestItemName
        {
            get
            {
                return _testItemName;
            }

            set
            {
                if (_testItemName == value)
                {
                    return;
                }

                RaisePropertyChanging(TestItemNamePropertyName);
                _testItemName = value;
                RaisePropertyChanged(TestItemNamePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="TestItemTypeDescription" /> property's name.
        /// </summary>
        public const string TestItemTypeDescriptionPropertyName = "TestItemTypeDescription";

        private string _testItemTypeDescription = string.Empty;

        /// <summary>
        /// Sets and gets the TestItemTypeDescription property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string TestItemTypeDescription
        {
            get
            {
                return _testItemTypeDescription;
            }

            set
            {
                if (_testItemTypeDescription == value)
                {
                    return;
                }

                RaisePropertyChanging(TestItemTypeDescriptionPropertyName);
                _testItemTypeDescription = value;
                RaisePropertyChanged(TestItemTypeDescriptionPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="TestPositionName" /> property's name. For ScoliosisATI ONLY.
        /// </summary>
        public const string TestPositionNamePropertyName = "TestPositionName";

        private string _testPositionName = string.Empty;

        /// <summary>
        /// Sets and gets the TestPositionName property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string TestPositionName
        {
            get
            {
                return _testPositionName;
            }

            set
            {
                if (_testPositionName == value)
                {
                    return;
                }

                RaisePropertyChanging(TestPositionNamePropertyName);
                _testPositionName = value;
                RaisePropertyChanged(TestPositionNamePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="TestDateDisplay" /> property's name.
        /// </summary>
        public const string TestDateDisplayPropertyName = "TestDateDisplay";

        private string _testDateDisplay = string.Empty;

        /// <summary>
        /// Sets and gets the TestDateDisplay property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string TestDateDisplay
        {
            get
            {
                return _testDateDisplay;
            }

            set
            {
                if (_testDateDisplay == value)
                {
                    return;
                }

                RaisePropertyChanging(TestDateDisplayPropertyName);
                _testDateDisplay = value;
                RaisePropertyChanged(TestDateDisplayPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="ResultRawData" /> property's name.
        /// </summary>
        public const string ResultRawDataPropertyName = "ResultRawData";

        private string _resultRawData = string.Empty;

        /// <summary>
        /// Sets and gets the ResultRawData property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string ResultRawData
        {
            get
            {
                return _resultRawData;
            }

            set
            {
                if (_resultRawData == value)
                {
                    return;
                }

                RaisePropertyChanging(ResultRawDataPropertyName);
                _resultRawData = value;
                RaisePropertyChanged(ResultRawDataPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="FormattedTestResult" /> property's name.
        /// </summary>
        public const string FormattedTestResultPropertyName = "FormattedTestResult";

        private string _formattedTestResult = string.Empty;

        /// <summary>
        /// Sets and gets the FormattedTestResult property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string FormattedTestResult
        {
            get
            {
                return _formattedTestResult;
            }

            set
            {
                if (_formattedTestResult == value)
                {
                    return;
                }

                RaisePropertyChanging(FormattedTestResultPropertyName);
                _formattedTestResult = value;
                RaisePropertyChanged(FormattedTestResultPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="FirstTestResultLabel" /> property's name.
        /// </summary>
        public const string FirstTestResultLabelPropertyName = "FirstTestResultLabel";

        private string _firstTestResultLabel = string.Empty;

        /// <summary>
        /// Sets and gets the FirstTestResultLabel property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string FirstTestResultLabel
        {
            get
            {
                return _firstTestResultLabel;
            }

            set
            {
                if (_firstTestResultLabel == value)
                {
                    return;
                }

                RaisePropertyChanging(FirstTestResultLabelPropertyName);
                _firstTestResultLabel = value;
                RaisePropertyChanged(FirstTestResultLabelPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="SecondTestResultLabel" /> property's name.
        /// </summary>
        public const string SecondTestResultLabelPropertyName = "SecondTestResultLabel";

        private string _secondTestResultLabel = string.Empty;

        /// <summary>
        /// Sets and gets the SecondTestResultLabel property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string SecondTestResultLabel
        {
            get
            {
                return _secondTestResultLabel;
            }

            set
            {
                if (_secondTestResultLabel == value)
                {
                    return;
                }

                RaisePropertyChanging(SecondTestResultLabelPropertyName);
                _secondTestResultLabel = value;
                RaisePropertyChanged(SecondTestResultLabelPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="FirstTestResult" /> property's name.
        /// </summary>
        public const string FirstTestResultPropertyName = "FirstTestResult";

        private int? _firstTestResult = null;

        /// <summary>
        /// Sets and gets the FirstTestResult property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public int? FirstTestResult
        {
            get
            {
                return _firstTestResult;
            }

            set
            {
                if (_firstTestResult == value)
                {
                    return;
                }

                RaisePropertyChanging(FirstTestResultPropertyName);
                _firstTestResult = value;
                RaisePropertyChanged(FirstTestResultPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="SecondTestResult" /> property's name.
        /// </summary>
        public const string SecondTestResultPropertyName = "SecondTestResult";

        private int? _secondTestResult = null;

        /// <summary>
        /// Sets and gets the SecondTestResult property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public int? SecondTestResult
        {
            get
            {
                return _secondTestResult;
            }

            set
            {
                if (_secondTestResult == value)
                {
                    return;
                }

                RaisePropertyChanging(SecondTestResultPropertyName);
                _secondTestResult = value;
                RaisePropertyChanged(SecondTestResultPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="FirstRangeStartValue" /> property's name.
        /// </summary>
        public const string FirstRangeStartValuePropertyName = "FirstRangeStartValue";

        private int _firstRangeStartValue = 0;

        /// <summary>
        /// Sets and gets the FirstRangeStartValue property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public int FirstRangeStartValue
        {
            get
            {
                return _firstRangeStartValue;
            }

            set
            {
                if (_firstRangeStartValue == value)
                {
                    return;
                }

                RaisePropertyChanging(FirstRangeStartValuePropertyName);
                _firstRangeStartValue = value;
                RaisePropertyChanged(FirstRangeStartValuePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="SecondRangeStartValue" /> property's name.
        /// </summary>
        public const string SecondRangeStartValuePropertyName = "SecondRangeStartValue";

        private int _secondRangeStartValue = 0;

        /// <summary>
        /// Sets and gets the SecondRangeStartValue property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public int SecondRangeStartValue
        {
            get
            {
                return _secondRangeStartValue;
            }

            set
            {
                if (_secondRangeStartValue == value)
                {
                    return;
                }

                RaisePropertyChanging(SecondRangeStartValuePropertyName);
                _secondRangeStartValue = value;
                RaisePropertyChanged(SecondRangeStartValuePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="FirstRangeEndValue" /> property's name.
        /// </summary>
        public const string FirstRangeEndValuePropertyName = "FirstRangeEndValue";

        private int _firstRangeEndValue = 0;

        /// <summary>
        /// Sets and gets the FirstRangeEndValue property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public int FirstRangeEndValue
        {
            get
            {
                return _firstRangeEndValue;
            }

            set
            {
                if (_firstRangeEndValue == value)
                {
                    return;
                }

                RaisePropertyChanging(FirstRangeEndValuePropertyName);
                _firstRangeEndValue = value;
                RaisePropertyChanged(FirstRangeEndValuePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="SecondRangeEndValue" /> property's name.
        /// </summary>
        public const string SecondRangeEndValuePropertyName = "SecondRangeEndValue";

        private int _secondRangeEndValue = 0;

        /// <summary>
        /// Sets and gets the SecondRangeEndValue property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public int SecondRangeEndValue
        {
            get
            {
                return _secondRangeEndValue;
            }

            set
            {
                if (_secondRangeEndValue == value)
                {
                    return;
                }

                RaisePropertyChanging(SecondRangeEndValuePropertyName);
                _secondRangeEndValue = value;
                RaisePropertyChanged(SecondRangeEndValuePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="FirstMaxValue" /> property's name.
        /// </summary>
        public const string FirstMaxValuePropertyName = "FirstMaxValue";

        private int _firstMaxValue = 0;

        /// <summary>
        /// Sets and gets the FirstMaxValue property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public int FirstMaxValue
        {
            get
            {
                return _firstMaxValue;
            }

            set
            {
                if (_firstMaxValue == value)
                {
                    return;
                }

                RaisePropertyChanging(FirstMaxValuePropertyName);
                _firstMaxValue = value;
                RaisePropertyChanged(FirstMaxValuePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="SecondMaxValue" /> property's name.
        /// </summary>
        public const string SecondMaxValuePropertyName = "SecondMaxValue";

        private int _secondMaxValue = 0;

        /// <summary>
        /// Sets and gets the SecondMaxValue property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public int SecondMaxValue
        {
            get
            {
                return _secondMaxValue;
            }

            set
            {
                if (_secondMaxValue == value)
                {
                    return;
                }

                RaisePropertyChanging(SecondMaxValuePropertyName);
                _secondMaxValue = value;
                RaisePropertyChanged(SecondMaxValuePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="GraphData" /> property's name. For ScoliosisATI ONLY.
        /// </summary>
        public const string GraphDataPropertyName = "GraphData";

        private ObservableCollection<KeyValuePair<int, double>> _graphData = new ObservableCollection<KeyValuePair<int, double>>();

        /// <summary>
        /// Sets and gets the GraphData property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public ObservableCollection<KeyValuePair<int, double>> GraphData
        {
            get
            {
                return _graphData;
            }

            set
            {
                if (_graphData == value)
                {
                    return;
                }

                RaisePropertyChanging(GraphDataPropertyName);
                _graphData = value;
                RaisePropertyChanged(GraphDataPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="GraphBaseLineData" /> property's name. For ScoliosisATI ONLY.
        /// </summary>
        public const string GraphBaseLineDataPropertyName = "GraphBaseLineData";

        private ObservableCollection<KeyValuePair<int, double>> _graphBaseLineData = new ObservableCollection<KeyValuePair<int, double>>();

        /// <summary>
        /// Sets and gets the GraphBaseLineData property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public ObservableCollection<KeyValuePair<int, double>> GraphBaseLineData
        {
            get
            {
                return _graphBaseLineData;
            }

            set
            {
                if (_graphBaseLineData == value)
                {
                    return;
                }

                RaisePropertyChanging(GraphBaseLineDataPropertyName);
                _graphBaseLineData = value;
                RaisePropertyChanged(GraphBaseLineDataPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="IsSelected" /> property's name.
        /// </summary>
        public const string IsSelectedPropertyName = "IsSelected";

        private bool _isSelected = false;

        /// <summary>
        /// Sets and gets the IsSelected property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public bool IsSelected
        {
            get
            {
                return _isSelected;
            }

            set
            {
                if (_isSelected == value)
                {
                    return;
                }

                RaisePropertyChanging(IsSelectedPropertyName);
                _isSelected = value;
                RaisePropertyChanged(IsSelectedPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="IsReadyToTest" /> property's name.
        /// </summary>
        public const string IsReadyToTestPropertyName = "IsReadyToTest";

        private bool _isReadyToTest = false;

        /// <summary>
        /// Sets and gets the IsReadyToTest property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public bool IsReadyToTest
        {
            get
            {
                return _isReadyToTest;
            }

            set
            {
                if (_isReadyToTest == value)
                {
                    return;
                }

                RaisePropertyChanging(IsReadyToTestPropertyName);
                _isReadyToTest = value;
                RaisePropertyChanged(IsReadyToTestPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="NeedDetailReport" /> property's name.
        /// </summary>
        public const string NeedDetailReportPropertyName = "NeedDetailReport";

        private bool _needDetailReport = false;

        /// <summary>
        /// Sets and gets the NeedDetailReport property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public bool NeedDetailReport
        {
            get
            {
                return _needDetailReport;
            }

            set
            {
                if (_needDetailReport == value)
                {
                    return;
                }

                RaisePropertyChanging(NeedDetailReportPropertyName);
                _needDetailReport = value;
                RaisePropertyChanged(NeedDetailReportPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="ReverseBackgroundColor" /> property's name.
        /// </summary>
        public const string ReverseBackgroundColorPropertyName = "ReverseBackgroundColor";

        private bool _reverseBackgroundColor = false;

        /// <summary>
        /// Sets and gets the ReverseBackgroundColor property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public bool ReverseBackgroundColor
        {
            get
            {
                return _reverseBackgroundColor;
            }

            set
            {
                if (_reverseBackgroundColor == value)
                {
                    return;
                }

                RaisePropertyChanging(ReverseBackgroundColorPropertyName);
                _reverseBackgroundColor = value;
                RaisePropertyChanged(ReverseBackgroundColorPropertyName);
            }
        }
    }
}
